"""
图片处理工具函数

提供图片缩略图、裁剪、水印等功能
"""

from pathlib import Path
from typing import Tuple, Optional
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from fastapi import HTTPException, status
import sys

# 处理导入路径
if __name__ == "__main__" or "." not in __name__:
    sys.path.insert(0, str(Path(__file__).parent.parent.parent))
    from stage2_advanced.chapter03_file_upload.config import (
        THUMBNAIL_SIZES,
        IMAGE_QUALITY,
        KEEP_ASPECT_RATIO,
        get_thumbnail_path,
    )
else:
    from .config import (
        THUMBNAIL_SIZES,
        IMAGE_QUALITY,
        KEEP_ASPECT_RATIO,
        get_thumbnail_path,
    )


# ========== 图片验证 ==========

def validate_image(image_path: Path) -> bool:
    """
    验证是否为有效的图片文件
    
    Args:
        image_path: 图片路径
        
    Returns:
        是否为有效图片
    """
    try:
        with Image.open(image_path) as img:
            img.verify()
        return True
    except Exception:
        return False


def get_image_info(image_path: Path) -> dict:
    """
    获取图片信息
    
    Args:
        image_path: 图片路径
        
    Returns:
        图片信息字典
    """
    try:
        with Image.open(image_path) as img:
            return {
                "width": img.width,
                "height": img.height,
                "format": img.format,
                "mode": img.mode,
                "size": image_path.stat().st_size,
            }
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Failed to read image: {str(e)}"
        )


# ========== 缩略图生成 ==========

def create_thumbnail(
    image_path: Path,
    size: Tuple[int, int] = (300, 300),
    output_path: Optional[Path] = None,
    keep_aspect_ratio: bool = KEEP_ASPECT_RATIO,
    quality: int = IMAGE_QUALITY
) -> Path:
    """
    创建缩略图
    
    Args:
        image_path: 原图片路径
        size: 缩略图尺寸 (width, height)
        output_path: 输出路径（可选，默认自动生成）
        keep_aspect_ratio: 是否保持宽高比
        quality: 图片质量（1-100）
        
    Returns:
        缩略图路径
    """
    try:
        with Image.open(image_path) as img:
            # 转换为 RGB 模式（处理 PNG 透明通道）
            if img.mode in ('RGBA', 'LA', 'P'):
                # 创建白色背景
                background = Image.new('RGB', img.size, (255, 255, 255))
                if img.mode == 'P':
                    img = img.convert('RGBA')
                background.paste(img, mask=img.split()[-1] if img.mode == 'RGBA' else None)
                img = background
            elif img.mode != 'RGB':
                img = img.convert('RGB')
            
            # 调整大小
            if keep_aspect_ratio:
                img.thumbnail(size, Image.Resampling.LANCZOS)
            else:
                img = img.resize(size, Image.Resampling.LANCZOS)
            
            # 确定输出路径
            if output_path is None:
                output_path = get_thumbnail_path(image_path.name, "medium")
            
            # 确保输出目录存在
            output_path.parent.mkdir(parents=True, exist_ok=True)
            
            # 保存缩略图
            img.save(output_path, quality=quality, optimize=True)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to create thumbnail: {str(e)}"
        )


def create_multiple_thumbnails(
    image_path: Path,
    sizes: dict = THUMBNAIL_SIZES
) -> dict:
    """
    创建多个尺寸的缩略图
    
    Args:
        image_path: 原图片路径
        sizes: 尺寸字典 {"small": (150, 150), ...}
        
    Returns:
        缩略图路径字典
    """
    thumbnails = {}
    
    for size_name, size_tuple in sizes.items():
        output_path = get_thumbnail_path(image_path.name, size_name)
        thumbnail_path = create_thumbnail(
            image_path,
            size=size_tuple,
            output_path=output_path
        )
        thumbnails[size_name] = thumbnail_path
    
    return thumbnails


# ========== 图片裁剪 ==========

def crop_image(
    image_path: Path,
    crop_box: Tuple[int, int, int, int],
    output_path: Optional[Path] = None
) -> Path:
    """
    裁剪图片
    
    Args:
        image_path: 原图片路径
        crop_box: 裁剪区域 (left, top, right, bottom)
        output_path: 输出路径
        
    Returns:
        裁剪后的图片路径
    """
    try:
        with Image.open(image_path) as img:
            cropped = img.crop(crop_box)
            
            if output_path is None:
                output_path = image_path.parent / f"{image_path.stem}_cropped{image_path.suffix}"
            
            cropped.save(output_path, quality=IMAGE_QUALITY)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to crop image: {str(e)}"
        )


def crop_center(
    image_path: Path,
    width: int,
    height: int,
    output_path: Optional[Path] = None
) -> Path:
    """
    从中心裁剪图片
    
    Args:
        image_path: 原图片路径
        width: 裁剪宽度
        height: 裁剪高度
        output_path: 输出路径
        
    Returns:
        裁剪后的图片路径
    """
    try:
        with Image.open(image_path) as img:
            # 计算中心点
            center_x = img.width // 2
            center_y = img.height // 2
            
            # 计算裁剪区域
            left = max(0, center_x - width // 2)
            top = max(0, center_y - height // 2)
            right = min(img.width, center_x + width // 2)
            bottom = min(img.height, center_y + height // 2)
            
            return crop_image(image_path, (left, top, right, bottom), output_path)
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to crop center: {str(e)}"
        )


# ========== 图片旋转 ==========

def rotate_image(
    image_path: Path,
    angle: int,
    output_path: Optional[Path] = None,
    expand: bool = True
) -> Path:
    """
    旋转图片
    
    Args:
        image_path: 原图片路径
        angle: 旋转角度（逆时针）
        output_path: 输出路径
        expand: 是否扩展画布以适应旋转后的图片
        
    Returns:
        旋转后的图片路径
    """
    try:
        with Image.open(image_path) as img:
            rotated = img.rotate(angle, expand=expand)
            
            if output_path is None:
                output_path = image_path.parent / f"{image_path.stem}_rotated{image_path.suffix}"
            
            rotated.save(output_path, quality=IMAGE_QUALITY)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to rotate image: {str(e)}"
        )


# ========== 图片水印 ==========

def add_text_watermark(
    image_path: Path,
    text: str,
    position: str = "bottom-right",
    output_path: Optional[Path] = None,
    opacity: int = 128,
    font_size: int = 36
) -> Path:
    """
    添加文字水印
    
    Args:
        image_path: 原图片路径
        text: 水印文字
        position: 位置（bottom-right/bottom-left/top-right/top-left/center）
        output_path: 输出路径
        opacity: 不透明度（0-255）
        font_size: 字体大小
        
    Returns:
        添加水印后的图片路径
    """
    try:
        with Image.open(image_path) as img:
            # 转换为 RGBA 以支持透明度
            if img.mode != 'RGBA':
                img = img.convert('RGBA')
            
            # 创建水印层
            watermark = Image.new('RGBA', img.size, (0, 0, 0, 0))
            draw = ImageDraw.Draw(watermark)
            
            # 尝试加载字体（如果失败则使用默认字体）
            try:
                font = ImageFont.truetype("arial.ttf", font_size)
            except:
                font = ImageFont.load_default()
            
            # 计算文字大小
            bbox = draw.textbbox((0, 0), text, font=font)
            text_width = bbox[2] - bbox[0]
            text_height = bbox[3] - bbox[1]
            
            # 计算位置
            margin = 10
            positions = {
                "bottom-right": (img.width - text_width - margin, img.height - text_height - margin),
                "bottom-left": (margin, img.height - text_height - margin),
                "top-right": (img.width - text_width - margin, margin),
                "top-left": (margin, margin),
                "center": ((img.width - text_width) // 2, (img.height - text_height) // 2),
            }
            
            pos = positions.get(position, positions["bottom-right"])
            
            # 绘制文字（白色文字，半透明黑色背景）
            draw.text(pos, text, fill=(255, 255, 255, opacity), font=font)
            
            # 合并图片和水印
            result = Image.alpha_composite(img, watermark)
            
            # 转换回 RGB
            result = result.convert('RGB')
            
            if output_path is None:
                output_path = image_path.parent / f"{image_path.stem}_watermark{image_path.suffix}"
            
            result.save(output_path, quality=IMAGE_QUALITY)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to add watermark: {str(e)}"
        )


# ========== 图片滤镜 ==========

def apply_filter(
    image_path: Path,
    filter_type: str,
    output_path: Optional[Path] = None
) -> Path:
    """
    应用滤镜
    
    Args:
        image_path: 原图片路径
        filter_type: 滤镜类型（blur/sharpen/smooth/edge_enhance）
        output_path: 输出路径
        
    Returns:
        处理后的图片路径
    """
    filters = {
        "blur": ImageFilter.BLUR,
        "sharpen": ImageFilter.SHARPEN,
        "smooth": ImageFilter.SMOOTH,
        "edge_enhance": ImageFilter.EDGE_ENHANCE,
        "contour": ImageFilter.CONTOUR,
        "detail": ImageFilter.DETAIL,
    }
    
    if filter_type not in filters:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Unknown filter type: {filter_type}. Available: {', '.join(filters.keys())}"
        )
    
    try:
        with Image.open(image_path) as img:
            filtered = img.filter(filters[filter_type])
            
            if output_path is None:
                output_path = image_path.parent / f"{image_path.stem}_{filter_type}{image_path.suffix}"
            
            filtered.save(output_path, quality=IMAGE_QUALITY)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to apply filter: {str(e)}"
        )


# ========== 图片格式转换 ==========

def convert_format(
    image_path: Path,
    target_format: str,
    output_path: Optional[Path] = None
) -> Path:
    """
    转换图片格式
    
    Args:
        image_path: 原图片路径
        target_format: 目标格式（JPEG/PNG/WEBP等）
        output_path: 输出路径
        
    Returns:
        转换后的图片路径
    """
    try:
        with Image.open(image_path) as img:
            # RGB 模式用于 JPEG
            if target_format.upper() == 'JPEG' and img.mode in ('RGBA', 'LA', 'P'):
                img = img.convert('RGB')
            
            if output_path is None:
                ext = f".{target_format.lower()}"
                output_path = image_path.parent / f"{image_path.stem}{ext}"
            
            img.save(output_path, format=target_format.upper(), quality=IMAGE_QUALITY)
            
            return output_path
            
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to convert format: {str(e)}"
        )

